package com.huiminpay.transaction.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.huiminpay.common.cache.domain.BusinessException;
import com.huiminpay.common.cache.domain.CommonErrorCode;
import com.huiminpay.common.cache.util.AmountUtil;
import com.huiminpay.common.cache.util.EncryptUtil;
import com.huiminpay.common.cache.util.PaymentUtil;
import com.huiminpay.merchant.api.AppService;
import com.huiminpay.merchant.api.MerchantService;
import com.huiminpay.paymentagent.api.PayChannelAgentService;
import com.huiminpay.paymentagent.api.conf.AliConfigParam;
import com.huiminpay.paymentagent.api.dto.AlipayBean;
import com.huiminpay.paymentagent.api.dto.PaymentResponseDTO;
import com.huiminpay.transaction.api.PayChannelService;
import com.huiminpay.transaction.api.TransactionService;
import com.huiminpay.transaction.api.dto.PayChannelParamDTO;
import com.huiminpay.transaction.api.dto.PayOrderDTO;
import com.huiminpay.transaction.api.dto.QRCodeDto;
import com.huiminpay.transaction.convert.PayOrderConvert;
import com.huiminpay.transaction.entity.PayOrder;
import com.huiminpay.transaction.mapper.PayOrderMapper;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

@Service  //dubbo注解
public class TransactionServiceImpl implements TransactionService {

    @Reference
    AppService appService;
    @Reference
    MerchantService merchantService;
    @Value("${huiminpay.payurl}")
    String payurl;
    @Autowired
    PayOrderMapper payOrderMapper;
    @Reference
    PayChannelAgentService agentService;
    @Autowired
    PayChannelService payChannelService;




    /**
     * 生成支付入口的url
     *
     * @param qrCodeDto 商户ID  应用ID,门店id,订单标题,订单描述
     * @return 支付入口的url
     * @throws BusinessException
     */

    public String createStoreQRCode(QRCodeDto qrCodeDto) throws BusinessException {

        //校验应用和门店是否属于该商户
        //如果不属于会在verifyAppAndStore方法中报异常终止服务运行
        verifyAppAndStore(qrCodeDto.getAppId(), qrCodeDto.getStoreId(), qrCodeDto.getMerchantId());

        //组装url上要带的参数
        PayOrderDTO payOrderDTO = new PayOrderDTO();
        payOrderDTO.setMerchantId(qrCodeDto.getMerchantId());
        payOrderDTO.setAppId(qrCodeDto.getAppId());
        payOrderDTO.setStoreId(qrCodeDto.getStoreId());
        payOrderDTO.setSubject(qrCodeDto.getSubject());//显示订单标题
        payOrderDTO.setChannel("huimin_c2b");//服务类型
        payOrderDTO.setBody(qrCodeDto.getBody());//订单内容

        //将对象转换为josn
        String param_json = JSON.toJSONString(payOrderDTO);
        String ticket = EncryptUtil.encodeUTF8StringBase64(param_json);
        // HTTP://localhost:56010/transaction/pay-entry/

        String url = payurl + ticket;

        return url;
    }

    /**
     * 根据订单号查询订单信息
     * @param tradeNo 订单号
     * @return 订单信息
     * @throws BusinessException
     */
    @Override
    public PayOrderDTO queryPayOrder(String tradeNo) throws BusinessException {
        PayOrder payOrder = payOrderMapper.selectOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getTradeNo, tradeNo));

        return PayOrderConvert.INSTANCE.entity2dto(payOrder);
    }

    /**
     * 校验应用和门店是否属于该商户
     *
     * @param appId      应用id
     * @param storeId    门店id
     * @param merchantId 商户id
     */
    private void verifyAppAndStore(String appId, Long storeId, Long merchantId) throws BusinessException {
        //判断应用是否属于当前商户
        if (!appService.isExist(appId, merchantId)) {
            throw new BusinessException(CommonErrorCode.E_200005);
        }
        //判断门店是否属于该商户
        if (!merchantService.queryStoreInMerchant(storeId, merchantId)) {
            throw new BusinessException(CommonErrorCode.E_200006);
        }

    }

    /**
     * 保存商户订单   调用支付渠道代理服务对接支付宝
     * @param payOrderDTO
     * @return
     * @throws BusinessException
     */
    @Override
    public PaymentResponseDTO<String> submitOrderByAli(PayOrderDTO payOrderDTO) throws BusinessException {

        payOrderDTO.setPayChannel("ALIPAY_WAP");
        //保存商户订单
        PayOrderDTO orderDTO = save(payOrderDTO);
        //调用支付渠道代理服务对接支付宝
        return alipayH5(orderDTO.getOutTradeNo());
    }

    /**
     * 更新订单
     *
     * @param tradeNo           商户订单号
     * @param payChannelTradeNo 支付渠道交易流水号
     * @param tradeState        订单状态
     * @throws BusinessException
     */
    @Override
    public void updateOrderTradeNoAndTradeState(String tradeNo, String payChannelTradeNo, String tradeState) throws BusinessException {
        //构造更新条件
        LambdaUpdateWrapper<PayOrder> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(PayOrder::getTradeNo,tradeNo)
                .set(PayOrder::getPayChannelTradeNo,payChannelTradeNo)
                .set(PayOrder::getTradeState,tradeState);
        payOrderMapper.update(null,wrapper);
    }

    /**
     * 保存订单
     *
     * @param payOrderDTO 订单信息
     * @return 新保存的订单信息
     * @throws BusinessException
     */
    private PayOrderDTO save(PayOrderDTO payOrderDTO) throws BusinessException {
        PayOrder payOrder = PayOrderConvert.INSTANCE.dto2entity(payOrderDTO);

        //订单号
        payOrder.setTradeNo(PaymentUtil.genUniquePayOrderNo());
        //创建时间
        payOrder.setCreateTime(LocalDateTime.now());
        //订单过期时间
        payOrder.setExpireTime(LocalDateTime.now().plus(30, ChronoUnit.MINUTES));
        //状态 0:订单生成
        payOrder.setTradeState("0");
        //设置币种
        payOrder.setCurrency("CNY");

        payOrderMapper.insert(payOrder);
        return PayOrderConvert.INSTANCE.entity2dto(payOrder);
    }

    /**
     * 调用支付渠道代理服务对接支付宝
     * @param tradeNo  订单号
     * @return  PaymentResponseDTO
     */
    private PaymentResponseDTO alipayH5(String tradeNo){
        PaymentResponseDTO paymentResponseDTO = new PaymentResponseDTO();
        //调用支付渠道代理服务对接支付宝
        //从数据库中查询到订单 组装AlipayBean参数
        PayOrderDTO payOrderDTO = queryPayOrder(tradeNo);
        AlipayBean alipayBean = new AlipayBean();
        alipayBean.setOutTradeNo(tradeNo);
        alipayBean.setSubject(payOrderDTO.getSubject());
        alipayBean.setBody(payOrderDTO.getBody());
        alipayBean.setStoreId(payOrderDTO.getStoreId());
        alipayBean.setExpireTime("30m");
        try {
            //将分转为元
            String totalAmount = AmountUtil.changeY2F(String.valueOf(payOrderDTO.getTotalAmount()));

        } catch (Exception e) {
            e.printStackTrace();
            throw  new BusinessException(CommonErrorCode.E_300006);
        }

        //组装AliConfigParam   支付渠道参数  从数据库中查
        PayChannelParamDTO payChannelParamDTO = payChannelService.queryParamByAppPlatformAndPayChannel(payOrderDTO.getAppId(), "huimin_c2b", "ALIPAY_WAP");
        if (payChannelParamDTO == null) {
            throw new BusinessException(CommonErrorCode.E_300007);
        }
        //取出支付参数
        String param = payChannelParamDTO.getParam();
        //转为AliConfigParam
        AliConfigParam aliConfigParam = JSON.parseObject(param, AliConfigParam.class);
        aliConfigParam.setCharest("UTF-8");


        return agentService.createPayOrderByAliWAP(aliConfigParam, alipayBean);
    }
}
